﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Data;
using System.IO;
using System.Linq;
using Zgq.CommonTools;

namespace Zgq.WpfTools
{
    public partial class CreateModel
    {


        public void CreateModelInfo(string dicPath, string tableName, string baseClassName, string nameSpace, List<DBTableColmnsInfo>  colmnsInfos)
        {

            if (string.IsNullOrWhiteSpace(dicPath))
                throw new Exception("文件路径不能为空");

            if (string.IsNullOrWhiteSpace(nameSpace))
                throw new Exception("命名空间不能为空");

            if (string.IsNullOrWhiteSpace(tableName))
                throw new Exception("表名或实图名不能为空");

            if (colmnsInfos == null || colmnsInfos.Count == 0)
                throw new Exception("表字段集合不能为空");

            if (!Directory.Exists(dicPath))
                Directory.CreateDirectory(dicPath);

            string allTxt = string.Empty;

            string filePath = string.Format(@"{0}\{1}.cs", dicPath, tableName);

            AddTableModel(ref allTxt, filePath, tableName, baseClassName, nameSpace, colmnsInfos);


            WriteModel(filePath, allTxt);
        }

        /// <summary>
        /// 写文件
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="allTxt"></param>
        private void WriteModel(string filePath, string allTxt)
        {
            File.WriteAllText(filePath, allTxt);
        }

        /// <summary>
        /// 读取表字段描述等信息
        /// </summary>
        /// <param name="allTxt"></param>
        /// <param name="filePath"></param>
        /// <param name="className"></param>
        /// <param name="sysEntitiesLineList"></param>
        /// <param name="IsDbData"></param>
        private void AddTableModel(ref string allTxt, string filePath, string className, string baseClassName, string nameSpace, List<DBTableColmnsInfo> colmnsInfos)
        {
            string currTableInfo = string.Empty;
            StringBuilder modelClassStringBuilder = new StringBuilder();
            //引用
            modelClassStringBuilder.AppendLine("using System;");
            modelClassStringBuilder.AppendLine("using System.Runtime.Serialization;");
            modelClassStringBuilder.AppendLine("using C5CommonTools;");
            modelClassStringBuilder.AppendLine("");

            //命名空间
            modelClassStringBuilder.AppendLine(string.Format("namespace {0}", nameSpace));
            modelClassStringBuilder.AppendLine("{");

            // = null;
            //if (IsDbData)
            //{
            //    var list = SLUtility.CallMethodList("SysEntities", "GetTableColumnInfo", entityCode);
            //    TColumnsList = list.Cast<DBTableColmnsInfo>().ToList();
            //}

            //对象特性
            string modelAttr = GetTableAttributes(colmnsInfos);
            if (!string.IsNullOrWhiteSpace(modelAttr))
                modelClassStringBuilder.AppendLine(string.Format("    {0}", modelAttr));

            //表
            currTableInfo = string.Format("public partial class {0} : {1}", className, baseClassName);
            modelClassStringBuilder.AppendLine(string.Format("    {0}", currTableInfo));
            modelClassStringBuilder.AppendLine("    {");

            //字段
            modelClassStringBuilder.AppendLine(GetColumnStr(colmnsInfos));

            //表
            modelClassStringBuilder.AppendLine("    }");

            //命名空间
            modelClassStringBuilder.AppendLine("}");

            allTxt = modelClassStringBuilder.ToString();
        }

        /// <summary>
        /// 获取字段信息
        /// </summary>
        /// <param name="IsDbData"></param>
        /// <param name="listEntity"></param>
        /// <param name="listTColumn"></param>
        /// <returns></returns>
        private string GetColumnStr(List<DBTableColmnsInfo> listTColumn)
        {
            StringBuilder modelClassStringBuilder = new StringBuilder();


            #region 数据库

            //循环写入列信息
            if (listTColumn != null && listTColumn.Count > 0)
            {
                listTColumn.ForEach(y =>
                {
                    //获取描述信息
                    string currColumnDescription = y.ReMark;

                    bool canNull = false;
                    if (!y.PrimaryKey && !y.AutoIncrement && y.IsNullable == 1)
                        canNull = true;

                    string currType = GetDataType(-1, y.DbType, canNull, 1);

                    //私有字段
                    modelClassStringBuilder.AppendLine(string.Format("        private {0} _{1};", currType, y.FieldName.Trim()));

                    //描述
                    modelClassStringBuilder.AppendLine("        /// <summary>");
                    modelClassStringBuilder.AppendLine(string.Format("        /// {0}", currColumnDescription));
                    modelClassStringBuilder.AppendLine("        /// </summary>");

                    //特性
                    modelClassStringBuilder.AppendLine(string.Format("        {0}", GetAttributes(y.AutoIncrement, y.PrimaryKey, y.DbType, y.MaxLength, y.Scale, y.Precision)));
                    //特性
                    modelClassStringBuilder.AppendLine("        [DataMember]");

                    //访问器
                    modelClassStringBuilder.AppendLine(string.Format("        public {0} {1}", currType, y.FieldName.Trim()));
                    modelClassStringBuilder.AppendLine("        {");
                    modelClassStringBuilder.AppendLine("            get");
                    modelClassStringBuilder.AppendLine("            {");
                    modelClassStringBuilder.AppendLine(string.Format("                return _{0};", y.FieldName.Trim()));
                    modelClassStringBuilder.AppendLine("            }");
                    modelClassStringBuilder.AppendLine("            set");
                    modelClassStringBuilder.AppendLine("            {");
                    modelClassStringBuilder.AppendLine(string.Format("                _{0} = value;", y.FieldName.Trim()));
                    modelClassStringBuilder.AppendLine(string.Format("                RaisePropertyChanged(\"{0}\");", y.FieldName.Trim()));
                    modelClassStringBuilder.AppendLine("            }");
                    modelClassStringBuilder.AppendLine("        }");
                });
            }

            #endregion


            return modelClassStringBuilder.ToString();
        }


        private string[] NotCanNull = new string[] { "string", "byte[]" };

        /// <summary>
        /// 获取C#和Sql Server数据类型
        /// </summary>
        /// <param name="dataType"></param>
        /// <param name="canNull"></param>
        /// <param name="type">1:C#类型 2:Sql类型 </param>
        /// <returns></returns>
        private string GetDataType(int dataType, string dbType, bool canNull, int type)
        {
            string result = null;
            DataType dType = SqlCache.GetDataTypeList().FirstOrDefault(x => x.SqlType == dbType);


            if (dType != null)
            {
                if (type == 1)
                    result = dType.CSharpType;
                else
                    result = dType.SqlType;

                if (type == 1 && canNull && NotCanNull.FirstOrDefault(x => x.Equals(result, StringComparison.CurrentCultureIgnoreCase)) == null)
                {
                    result = string.Format("{0}?", result);
                }
            }
            else
            {
                throw new Exception("未能找到字段类型信息");
            }

            return result;
        }

        /// <summary>
        /// 获取特性
        /// </summary>
        /// <param name="isIdentity"></param>
        /// <param name="isKey"></param>
        /// <returns></returns>
        private string GetAttributes(bool isIdentity, bool isKey, string dataType, int maxLength, int scale, int precision)
        {
            StringBuilder resultAttributes = new StringBuilder();

            //key
            if (isKey)
                resultAttributes.Append("PrimaryKey = true, ");

            //自增
            if (isIdentity)
                resultAttributes.Append("AutoIncrement = true, ");

            //时间戳
            if (dataType == "timestamp")
                resultAttributes.Append("IsTimeStamp = true, ");

            //数据类型
            if (!string.IsNullOrWhiteSpace(dataType))
                resultAttributes.AppendFormat("DbType = \"{0}\", ", dataType);

            //最大
            if (maxLength != 0 && (dataType == "varchar" || dataType == "nvarchar" || dataType == "text"))
                resultAttributes.AppendFormat("MaxLength = {0}, ", maxLength);

            //最小
            if (scale != 0)
                resultAttributes.AppendFormat("Scale = {0}, ", scale);

            //精度
            if (precision != 0)
                resultAttributes.AppendFormat("Precision = {0}, ", precision);

            return string.Format("[C5SqlModel({0})]", resultAttributes.ToString().Trim().Trim(','));
        }

        /// <summary>
        /// 对象特性
        /// </summary>
        /// <param name="listEntity"></param>
        /// <returns></returns>
        private string GetTableAttributes(List<DBTableColmnsInfo> listTColumn = null)
        {
            StringBuilder sb = new StringBuilder();

            var resultList = listTColumn.Where(x => x.PrimaryKey).ToList();
            foreach (var item in resultList)
            {
                sb.AppendFormat("{0}, ", item.FieldName.Trim());
            }

            if (string.IsNullOrWhiteSpace(sb.ToString()))
                return "";

            return string.Format("[C5ClassModel(PrimaryKeys = \"{0}\")]", sb.ToString().Trim().Trim(','));
        }

        /// <summary>
        /// 文件夹名称排序（顺序）
        /// </summary>
        /// <param name="dirs">待排序文件夹数组</param>
        private void SortAsFolderName(ref FileInfo[] files)
        {
            Array.Sort(files, delegate (FileInfo x, FileInfo y) { return x.Name.CompareTo(y.Name); });
        }

        #region 分文件

        /// <summary>
        /// 判断是否要创建新的文件
        /// </summary>
        /// <param name="filePath"></param>
        private void HandleAndCreateFile(ref string filePath)
        {
            string newPath = null;
            int maxCount = 500;
            //文件行数超过额定行数则创建新文件
            var rowCount = File.ReadAllLines(filePath).Length;
            if (rowCount > maxCount)
            {
                string fName = filePath.Substring(filePath.LastIndexOf(@"\")).Replace(@"\", "");
                if (!string.IsNullOrWhiteSpace(fName))
                {
                    List<FileInfo> list = new List<FileInfo>();
                    var files = new DirectoryInfo(filePath.Replace(fName, "")).GetFiles("*.cs");
                    foreach (var item in files)
                    {
                        if (item.Name.Equals(fName))
                        {
                            list.Add(item);
                            continue;
                        }

                        if (item.Name.Contains(fName.Replace(".cs", "")) && item.Name.Contains("_"))
                            list.Add(item);
                    }

                    var fileInfos = list.ToArray();
                    SortAsFolderName(ref fileInfos);

                    if (fileInfos.Length > 0)
                    {
                        var fileInfo = fileInfos[fileInfos.Length - 1];
                        if (fileInfo != null)
                        {
                            if (File.ReadAllLines(fileInfo.FullName).Length <= maxCount)
                            {
                                filePath = fileInfo.FullName;
                                return;
                            }

                            string name = "";
                            if (fileInfo.Name.Contains("_"))
                            {
                                string[] strName = fileInfo.Name.Replace(fileInfo.Extension, "").Split('_');
                                name = string.Format("{0}_{1}", strName[0], Convert.ToInt32(strName[1]) + 1);
                            }
                            else
                            {
                                name = string.Format("{0}_1", fileInfo.Name.Replace(fileInfo.Extension, ""));
                            }

                            newPath = string.Format(@"{0}\{1}.cs", fileInfo.DirectoryName, name);
                        }
                    }
                }
            }

            //写入文件引用及命名空间
            if (!string.IsNullOrWhiteSpace(newPath))
            {
                string str = File.ReadAllText(filePath);
                string otherStr = str.Substring(str.IndexOf("public", StringComparison.CurrentCultureIgnoreCase));

                StringBuilder sbstr = new StringBuilder();
                sbstr.Append(str.Replace(otherStr, ""));
                sbstr.Append("}");

                WriteModel(newPath, sbstr.ToString());
                filePath = newPath;
            }
        }

        #endregion

        #region 表说明

        /// <summary>
        /// EEP配置表说明
        /// </summary>
        private class TableColumnDescriptionByHG_C5Model
        {
            /// <summary>
            /// 表名
            /// </summary>
            public string ENTITY_CODE { get; set; }

            /// <summary>
            /// 字段
            /// </summary>
            public string FIELD_CODE { get; set; }

            /// <summary>
            /// 默认名称
            /// </summary>
            public string DefaultCaption { get; set; }
        }

        #endregion

    }
}
